﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Comdiv.QWeb.Factory;

namespace Comdiv.QWeb.Binding {
	public class DefaultActionBinder : IActionBinder {
		#region IActionBinder Members

		public bool IsBindable(Type actionType) {
			var members =
				actionType.GetMembers(BindingFlags.SetField | BindingFlags.SetProperty | BindingFlags.Instance |
				                      BindingFlags.Public | BindingFlags.NonPublic);
			foreach (var m in members) {
				if (m.GetCustomAttributes(typeof (BindAttribute), true).Length != 0) {
					return true;
				}
			}
			return false;
		}

		public void Bind(ActionDescriptor action, QWebContext context) {
			lock (this) {
				//check that bindable members are indexed
				if (null == action.Binders) {
					SetupBinders(action);
				}
				foreach (var binder in action.Binders) {
					binder.Bind(action, context);
				}
			}
		}

		#endregion

		public void SetupBinders(ActionDescriptor action) {
			if (null == action.TypeDescriptor.Binders) {
				var members =
					action.TypeDescriptor.ActionType.GetMembers(BindingFlags.SetField | BindingFlags.SetProperty |
					                                            BindingFlags.Instance |
					                                            BindingFlags.Public | BindingFlags.NonPublic);
				var result = new List<BindAttribute>();
				foreach (var m in members) {
					if (m.GetCustomAttributes(typeof (BindAttribute), true).Length != 0) {
						var a = m.GetCustomAttributes(typeof (BindAttribute), true)[0] as BindAttribute;
						result.Add(a.GetThreadSafeCopy(m));
					}
				}
				action.TypeDescriptor.Binders = result.ToArray();
			}
			action.Binders = action.TypeDescriptor.Binders.Select(x => x.GetThreadSafeCopy()).ToArray();
		}
	}
}